package com.icetech.eom.controller.sys;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.icetech.api.SmgService;
import com.icetech.api.domain.ApiBaseRequest;
import com.icetech.api.domain.request.sms.SmsRequest;
import com.icetech.commonbase.ResultTools;
import com.icetech.commonbase.UUIDTools;
import com.icetech.commonbase.constants.CodeConstantsEnum;
import com.icetech.commonbase.domain.Page;
import com.icetech.commonbase.domain.response.ObjectResponse;
import com.icetech.eom.common.annotation.SystemLog;
import com.icetech.eom.common.constant.SecurityConstant;
import com.icetech.eom.common.constant.UserTypeEnum;
import com.icetech.eom.controller.BaseController;
import com.icetech.eom.controller.vo.UserVo;
import com.icetech.eom.dao.sys.CustomDao;
import com.icetech.eom.dao.tx.DeviceDao;
import com.icetech.eom.dao.tx.UDevDao;
import com.icetech.eom.domain.sys.Custom;
import com.icetech.eom.domain.sys.Role;
import com.icetech.eom.domain.sys.User;
import com.icetech.eom.domain.sys.UserRole;
import com.icetech.eom.domain.tx.Device;
import com.icetech.eom.domain.tx.UDev;
import com.icetech.eom.domain.tx.dto.UserBindDto;
import com.icetech.eom.domain.tx.dto.UserDto;
import com.icetech.eom.service.sys.IRoleService;
import com.icetech.eom.service.sys.IUserRoleService;
import com.icetech.eom.service.tx.IUDevService;
import com.icetech.eom.service.tx.IUserService;
import com.icetech.eom.service.utils.SecurityUtil;
import com.sargeraswang.util.ExcelUtil.ExcelLogs;
import com.sargeraswang.util.ExcelUtil.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author wangzw
 * @since 2018-11-12
 */
@RestController
@RequestMapping("/user")
@Api(description = "用户接口详细信息的描述")
@Slf4j
public class UserController extends BaseController {
    private static Md5PasswordEncoder md5encoder = new Md5PasswordEncoder();
    @Autowired
    private IUserService userService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SmgService smgService;
    @Autowired
    private SecurityUtil securityUtil;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUDevService iuDevService;
    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private UDevDao uDevDao;
    @Autowired
    private CustomDao customDao;

    /**
     * 获取用户列表
     */
    @ApiOperation(value = "获取用户列表", notes = "根据查询信息获取用户列表，返回List<UserDto>类型用户信息的JSON")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "searchKey", value = "关键字", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "page", value = "当前页数", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "pageSize", value = "每页展示条数", paramType = "query", dataType = "int")
    })
    @RequestMapping(value = "/listpage",method = RequestMethod.GET)
    @SystemLog(description = "获取用户列表")
    public ObjectResponse<Page> getUsers(@RequestParam(value = "searchKey",defaultValue = "")String searchKey,
                                           @RequestParam(value = "userType",defaultValue = "")Integer userType,
                                           @RequestParam(value = "page",defaultValue = "1")Integer page,
                                           @RequestParam(value = "pageSize",defaultValue = "20")Integer pageSize){
        //获取列表信息
        User currUser = securityUtil.getCurrUser();
        PageInfo<UserDto> pageInfo = userService.selectByPage(searchKey, page, pageSize,userType,currUser.getOrgId());
        return ResultTools.getPageResponse(pageInfo.getList(),pageInfo.getTotal(),pageInfo.getPages());
    }

    /**
     * 增加
     */
    @ApiOperation(value = "用户添加", notes = "添加用户信息")
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @SystemLog(description = "用户添加")
    @Transactional
    public ObjectResponse add(@RequestBody UserVo userVo){
        User loginUser = securityUtil.getCurrUser();
        User user = new User();
        BeanUtils.copyProperties(userVo, user);
        User username = userService.findByUsername(user.getMobileNo());
        if (Objects.nonNull(username)){
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),"该用户已存在");
        }
        user.setCreator(loginUser.getUserName());
        user.setPwd(md5encoder.encodePassword("123456",""));
        Custom custom = customDao.selectById(user.getOrgId());
        if (Objects.nonNull(custom))user.setCompName(custom.getCompanyName());
        //添加管理员的时候赋予管理员的角色
        List<Long> roleIds = Lists.newArrayList();
        if (userVo.getUserType().equals(UserTypeEnum.manager.getType())){
            List<Role> roles = roleService.getDefaultRole();
            if (!CollectionUtils.isEmpty(roles)){
                roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
            }
        }
        //添加子账户关联当前登录账户的客户信息
        if (userVo.getUserType().equals(UserTypeEnum.subuser.getType())){
            user.setOrgId(loginUser.getOrgId());
        }
        boolean isSuccess = userService.saveUserAndRole(user,roleIds);

        //如果添加的是操作者账号自动绑定当前操作者下的设备
        if (userVo.getUserType().equals(UserTypeEnum.operater.getType()) || userVo.getDevPl()!=null){
            //获取当前开发者下的设备信息
            List<Device> bindDevices = deviceDao.selectByUserIdAndSearchKey(null, userVo.getDevPl());
            //绑定设备
            if (!CollectionUtils.isEmpty(bindDevices)){
                bindDevices.forEach(device -> {
                    UDev uDev = new UDev();
                    uDev.setUserId(user.getId());
                    uDev.setDevId(device.getId());
                    uDev.setCreator(loginUser.getUserName());
                    uDevDao.insert(uDev);
                });
            }
        }
        return isSuccess?ResultTools.success(null):ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
    }

    /**
     * 编辑用户
     */
    @ApiOperation(value = "用户编辑", notes = "编辑用户信息")
    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    @SystemLog(description = "用户编辑")
    public ObjectResponse edit(@RequestBody UserVo userVo){
        User loginUser =securityUtil.getCurrUser();
        User user = new User();
        BeanUtils.copyProperties(userVo, user);
        if (StringUtils.isNotBlank(userVo.getPwd())){
            user.setPwd(md5encoder.encodePassword(userVo.getPwd(),""));
        }else {
            User dbUser = userService.getById(user.getId());
            user.setPwd(dbUser.getPwd());
        }
        user.setModifier(loginUser.getUserName());
        boolean isSuccess = userService.updateById(user);
        return isSuccess?ResultTools.success(null):ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
    }


    /**
     * 删除用户
     */
    @ApiOperation(value = "用户删除", notes = "删除用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", paramType = "query", dataType = "int")
    })
    @RequestMapping(value = "/remove",method = RequestMethod.GET)
    @SystemLog(description = "用户删除")
    @Transactional
    public ObjectResponse remove(@RequestParam("id")Long id){
        User user = userService.getById(id);
        if (Objects.isNull(user)){
            return ResultTools.fail(CodeConstantsEnum.ERROR_404.getCode(),CodeConstantsEnum.ERROR_404.getDesc());
        }
        boolean isSuccess = userService.removeById(id);
        //删除设备用户绑定关系
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("user_id",id);
        uDevDao.deleteByMap(params);
        return isSuccess?ResultTools.success(null):ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
    }
    /**
     * 删除批量删除
     */
    @ApiOperation(value = "用户批量删除", notes = "批量删除用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "id组成的数组", paramType = "query", dataType = "int")
    })
    @RequestMapping(value = "/batchremove",method = RequestMethod.GET)
    @Transactional
    @SystemLog(description = "用户批量删除")
    public ObjectResponse batchRemove(@RequestParam("ids") List<Long> ids){
        boolean isSuccess = userService.removeByIds(ids);
        //删除用户与设备的绑定关系
        ids.forEach(integer -> {
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("user_id",integer);
            uDevDao.deleteByMap(params);
        });
        return isSuccess?ResultTools.success(null):ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
    }

    /**
     * 导出操作
     */
    @ApiOperation(value = "用户批量导出", notes = "批量导出用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "searchKey", value = "关键字", paramType = "query", dataType = "String")
    })
    @RequestMapping(value = "/export",method = RequestMethod.GET)
    @SystemLog(description = "用户批量导出")
    public ObjectResponse export(@RequestParam(value = "searchKey",defaultValue = "") String searchKey,
                                 @RequestParam(value = "userType",defaultValue = "") Integer userType,
                                 HttpServletResponse response){
        try {
            User currUser = securityUtil.getCurrUser();
            Workbook workbook = userService.exportExcel(searchKey,userType,currUser.getOrgId());
            String fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".xls";
            setFileResponse(response, fileName);
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
        }
        return ResultTools.success(null);
    }

    /**
     * 发送验证码
     */
    @ApiOperation(value = "用户短信发送", notes = "用户短信发送")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobileNo", value = "手机", paramType = "query", dataType = "String")
    })
    @RequestMapping(value = "/sendsmg",method = RequestMethod.GET)
    @SystemLog(description = "用户短信发送")
    public ObjectResponse sendMsg(@RequestParam("mobileNo") String mobileNo) throws Exception {
        //产生验证码
        String code = UUIDTools.getNonce_str(4);
        SmsRequest smsRequest = new SmsRequest();
        smsRequest.setContent("【智芯云】您的验证码为"+ code +"有效期为5分钟");
        smsRequest.setDesMobile(mobileNo);
        smsRequest.setTimes(60);
        ApiBaseRequest<SmsRequest> baseRequest = new ApiBaseRequest<SmsRequest>();
        baseRequest.setBizContent(smsRequest);
        ObjectResponse<String> response = smgService.sendMsg(baseRequest);
        if (!response.getCode().equals(CodeConstantsEnum.SUCCESS.getCode()))
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),CodeConstantsEnum.ERROR.getDesc());
        //将验证码放入redis 有效期为5分钟
        redisTemplate.opsForValue().set(SecurityConstant.PC_MSG_PRE+mobileNo, code, 5, TimeUnit.MINUTES);
        return ResultTools.success(null);
    }

    @ApiOperation(value = "获取当前登录用户信息", notes = "获取当前登录用户信息")
    @RequestMapping("/getCurrent")
    @SystemLog(description = "获取当前登录用户信息")
    public ObjectResponse getCurrent(){

        return ResultTools.success(securityUtil.getCurrUser());
    }

    @ApiOperation(value = "给用户分配权限", notes = "给用户分配权限")
    @RequestMapping("/editUserRole")
    @SystemLog(description = "给用户分配权限")
    public ObjectResponse editUserRole(@RequestBody UserVo userVo){
        User currUser = securityUtil.getCurrUser();
        //删除用户绑定的角色
        userRoleService.deleteByUserId(userVo.getId());
        //重新分配角色
        userVo.getRoleIds().forEach(roleId->{
            UserRole userRole = new UserRole();
            userRole.setUserId(userVo.getId());
            userRole.setRoleId(roleId);
            userRole.setCreateBy(currUser.getUserName());
            userRoleService.save(userRole);
        });
        return ResultTools.success(null);
    }

    @ApiOperation(value = "获取用户角色", notes = "给用户分配权限")
    @RequestMapping("/getUserRole")
    @SystemLog(description = "获取用户角色")
    public ObjectResponse getUserRole(Long userId){
        //已经拥有的角色
        List<Role> yesRoles = userRoleService.findByUserId(userId);
        List<Long> roleIds = yesRoles.stream().map(Role::getId).collect(Collectors.toList());
        return ResultTools.success(roleIds);
    }

    @ApiOperation(value = "获取开发者信息", notes = "获取开发者信息")
    @RequestMapping("/getDevUsers")
    @SystemLog(description = "获取开发者信息")
    public ObjectResponse getDevUsers(){
        return ResultTools.success(userService.findAllDeveloper());
    }

    @ApiOperation(value = "获取绑定设备信息", notes = "获取绑定设备信息")
    @RequestMapping("/getBindDevices")
    @SystemLog(description = "获取绑定设备信息")
    public ObjectResponse getBindDevices(@RequestParam("userId") Long userId){
        //获取当前用户绑定的设备信息
        List<Device> list  = deviceDao.selectByUserIdAndSearchKey(null, userId);
        return ResultTools.success(list);
    }

    @ApiOperation(value = "批量绑定设备",notes = "批量绑定设备")
    @RequestMapping("/batchBindDevice")
    @SystemLog(description = "批量绑定设备")
    @Transactional
    public ObjectResponse batchBindDevice(@RequestParam("userId") Long userId,@RequestParam("deviceIds")List<Long> deviceIds){
        User currUser = securityUtil.getCurrUser();
        //批量绑定
        if (CollectionUtils.isEmpty(deviceIds)){
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),"无效数据");
        }
        //如果当前用户是开发者则开发者下的操作者也都进行设备绑定
        User bindUser = userService.getById(userId);
        if (Objects.nonNull(bindUser)&&bindUser.getUserType().equals(UserTypeEnum.developer.getType())){
            //获取当前开发者下的操作者
            List<User> operaters = userService.getOperatersByDev(userId);
            if (!CollectionUtils.isEmpty(operaters)){
                //操作者账号进行绑定
                operaters.forEach(user -> {
                    ArrayList<UDev> saves = Lists.newArrayList();
                    deviceIds.forEach(deviceId -> {
                        //查询当前是否绑定
                        UDev uDev = iuDevService.selectByUserIdAndDevId(deviceId, user.getId());
                        if (Objects.isNull(uDev)){
                            UDev newDev = new UDev();
                            newDev.setUserId(user.getId());
                            newDev.setDevId(deviceId);
                            newDev.setBindTime(new Date());
                            newDev.setCreator(currUser.getUserName());
                            saves.add(newDev);
                        }
                    });
                    iuDevService.saveBatch(saves);
                });
            }
        }

        //绑定当前用户
        ArrayList<UDev> saves = Lists.newArrayList();
        deviceIds.forEach(deviceId -> {
            //查询当前是否绑定
            UDev uDev = iuDevService.selectByUserIdAndDevId(deviceId, userId);
            if (Objects.isNull(uDev)){
                //更新设备绑定信息
                Device device = deviceDao.selectById(deviceId);
                device.setBindUserId(userId);
                device.setBindTime(new Date());
                deviceDao.updateById(device);
                UDev newDev = new UDev();
                newDev.setUserId(userId);
                newDev.setDevId(deviceId);
                newDev.setBindTime(new Date());
                newDev.setCreator(currUser.getUserName());
                saves.add(newDev);
            }
        });
        iuDevService.saveBatch(saves);
        return ResultTools.success(null);
    }
    @ApiOperation(value = "批量解除绑定设备",notes = "批量解除绑定设备")
    @RequestMapping("/batchUnBindDevice")
    @SystemLog(description = "批量解除绑定设备")
    public ObjectResponse batchUnBindDevice(@RequestParam("userId") Long userId,@RequestParam("deviceIds")List<Long> deviceIds){
        //批量解除绑定
        if (CollectionUtils.isEmpty(deviceIds)){
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),"无效数据");
        }
        deviceIds.forEach(deviceId -> {
            //查询当前是否绑定
            UDev uDev = iuDevService.selectByUserIdAndDevId(deviceId, userId);
            if (Objects.nonNull(uDev)){
                //删除绑定信息
                Map<String,Object> params = Maps.newHashMap();
                params.put("user_id",userId);
                params.put("dev_id",deviceId);
                uDevDao.deleteByMap(params);
            }
        });
        return ResultTools.success(null);
    }


    @ApiOperation(value = "批量绑定导入", notes = "批量绑定导入")
    @RequestMapping(value = "bindImport",method = RequestMethod.POST)
    @SystemLog(description = "批量绑定导入")
    public ObjectResponse bindImport(@RequestParam(value="file",required=false) MultipartFile file) throws IOException {
        User userEntity = securityUtil.getCurrUser();
        Collection<Map> maps = ExcelUtil.importExcel(Map.class,file.getInputStream(),"yyyy/MM/dd HH:mm:ss",new ExcelLogs(),0);
        ArrayList<UDev> saves = Lists.newArrayList();
        maps.forEach(obj->{
            UserBindDto userBindDto = new UserBindDto();
            String guid = (String) obj.get("设备UID");
            String userName = (String) obj.get("用户账号");

            log.info("<当前导入设备uuid>: {}",guid);
            log.info("<当前绑定的用户>: {}",userName);
            userBindDto.setGuid(guid.trim());
            userBindDto.setUserName(userName.trim());
            //获取用户信息
            User userInfo = userService.findByUsername(userBindDto.getUserName());
            //获取设备信息
            Device deviceInfo = deviceDao.selectByGuid(userBindDto.getGuid());
            if (Objects.nonNull(userInfo) && Objects.nonNull(deviceInfo)){
                if (Objects.nonNull(userInfo)&&userInfo.getUserType().equals(UserTypeEnum.developer.getType())){
                    //获取当前添加操作者绑定信息
                    List<User> operaters = userService.getOperatersByDev(userInfo.getId());
                    if (!CollectionUtils.isEmpty(operaters)){
                        operaters.forEach(user -> {
                            if (Objects.nonNull(deviceInfo)){
                                UDev uDev = iuDevService.selectByUserIdAndDevId(deviceInfo.getId(), user.getId());
                                if (Objects.isNull(uDev)) {
                                    UDev newDev = new UDev();
                                    newDev.setUserId(user.getId());
                                    newDev.setDevId(deviceInfo.getId());
                                    newDev.setBindTime(new Date());
                                    newDev.setCreator(userEntity.getUserName());
                                    log.info("<当前绑定用户和设备>",user.getMobileNo(),deviceInfo.getGuid());
                                    saves.add(newDev);
                                }
                            }
                        });
                    }
                }
                //添加当前导入的的账号设备信息
                UDev uDev = iuDevService.selectByUserIdAndDevId(deviceInfo.getId(), userInfo.getId());
                if (Objects.isNull(uDev)) {
                    deviceInfo.setBindUserId(userInfo.getId());
                    deviceInfo.setBindTime(new Date());
                    deviceDao.updateById(deviceInfo);
                    UDev newDev = new UDev();
                    newDev.setUserId(userInfo.getId());
                    newDev.setDevId(deviceInfo.getId());
                    newDev.setBindTime(new Date());
                    newDev.setCreator(userEntity.getUserName());
                    log.info("<当前绑定用户和设备>",userInfo.getMobileNo(),deviceInfo.getGuid());
                    saves.add(newDev);
                }
            }

        });
        if (!CollectionUtils.isEmpty(saves)){
            iuDevService.saveBatch(saves);
        }
        return ResultTools.success(null);
    }

    /**
     * 更新密码
     */
    @ApiOperation(value = "修改密码", notes = "编辑用户信息")
    @RequestMapping(value = "/updatePwd",method = RequestMethod.GET)
    @SystemLog(description = "修改密码")
    public ObjectResponse updatePwd(@RequestParam("userId") Long userId,@RequestParam("pwd") String pwd){
        //查看当前用户
        User user = userService.getById(userId);
        if (Objects.isNull(user)){
            return ResultTools.fail(CodeConstantsEnum.ERROR.getCode(),"用户不存在");
        }
        user.setPwd(md5encoder.encodePassword(pwd,""));
        userService.updateById(user);
        return ResultTools.success(null);
    }
}
